#include "OpennavReverseGeocodingServiceProvider.h"

OpennavReverseGeocodingServiceProvider::OpennavReverseGeocodingServiceProvider()
	: __pMap(null), __pGeocodingWorker(null), __pLock(null), __pRequestListener(null), __kill(false), __activate(false) {

}

OpennavReverseGeocodingServiceProvider::~OpennavReverseGeocodingServiceProvider() {
	if (__pGeocodingWorker != null) {
		__kill = true;
		__pGeocodingWorker->Join();
		delete __pGeocodingWorker;
		__pGeocodingWorker = null;
	}
	if (__pLock != null) {
		delete __pLock;
		__pLock = null;
	}
}

result OpennavReverseGeocodingServiceProvider::Construct(OpennavMap* map) {
	__pMap = map;
	__pGeocodingWorker = new Thread();
	__pGeocodingWorker->Construct(L"RenderWorker", *this, Thread::DEFAULT_STACK_SIZE, THREAD_PRIORITY_LOW);
	__pGeocodingWorker->Start();
	__pLock = new Mutex();
	__pLock->Create();
	return E_SUCCESS;
}

void OpennavReverseGeocodingServiceProvider::ReverseGeocodeRoad(const Osp::Locations::Coordinates& coordinate, IOpennavReverseGeocodeListener& listener) {
	__pLock->Acquire();
	AppLogDebug("reverse geocoding request");
	__activate = true;
	__pRequestListener = &listener;
	__coordinate = coordinate;
	__pLock->Release();
}

Osp::Base::Object* OpennavReverseGeocodingServiceProvider::Run(void) {
	AppLogDebug("geocoding worker started");
	while(__kill == false) {
		if (__activate) {
			AppLogDebug("geocoding worker awakes");
			__pLock->Acquire();
			__activate = false;
			Osp::Locations::Coordinates coordinate = __coordinate;
			IOpennavReverseGeocodeListener* pListener = __pRequestListener;
			__pLock->Release();
			if (pListener != null) {
				opennav::Road road;
				opennav::RoadSegment segment;
				opennav::RoadJunction nextJunction;
				Osp::Locations::Coordinates coordout;
				if (__pMap->ReverseGeocode(coordinate, road, segment, nextJunction, coordout)) {
					pListener->OnReverseGeocodeResultReceived(road, segment, nextJunction, coordout);
				} else {
					pListener->OnNoReverseGeocodeResultReceived();
				}
			}
		} else {
			Thread::GetCurrentThread()->Sleep(0);
		}
	}
	AppLogDebug("geocoding worker terminated");
	return null;
}
